package com.zx.flow.config;

import com.auth0.jwt.exceptions.JWTVerificationException;
import com.zx.flow.api.exception.FlowException;
import com.zx.flow.api.execute.response.Response;
import com.zx.flow.api.execute.response.ResponseStatus;
import com.zx.flow.api.util.ValidUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @version v1.0
 * @Project: lab_000_base_web
 * @Title: GlobalExceptionHandler
 * @Description: 全局异常处理
 * @author: zhangxue01
 * @date: 2020-9-18 20:09:41
 * @company: zhangxue
 * @Copyright: Copyright (c) 2015
 */
@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    /**
     * BindException异常处理【当BindingResult中存在错误信息时，会抛出BindException异常】
     */
    @ExceptionHandler({BindException.class})
    public Response handleBindExceptionException(HttpServletRequest req, BindException e) {
        log.error("参数校验失败", e);
        return Response.fail(ResponseStatus.FLOW_ERROR_701, ValidUtil.getError(e.getBindingResult()));
    }

    /**
     * MethodArgumentNotValidException异常处理【MethodArgumentNotValidException异常校验 @RequestBody标注的JSON对象参数】
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Response handleMethodArgumentNotValidException(HttpServletRequest req, MethodArgumentNotValidException e) {
        log.error("参数校验失败[@RequestBody]", e);
        return Response.fail(ResponseStatus.FLOW_ERROR_701, ValidUtil.getError(e.getBindingResult()));
    }

    /**
     * ConstraintViolationException异常处理【单个参数异常处理】
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public Response handleConstraintViolationException(HttpServletRequest req, ConstraintViolationException e) {
        log.error("参数校验失败[单个参数异常处理]", e);
        return Response.fail(ResponseStatus.FLOW_ERROR_701, ValidUtil.getError(e.getConstraintViolations()));
    }

    /**
     * 流程处理出现异常
     */
    @ExceptionHandler({FlowException.class})
    public Response handleFlowException(HttpServletRequest req, FlowException e) {
        log.error("流程处理失败", e);
        return Response.fail(ResponseStatus.FLOW_ERROR_801, e.getMessage());
    }

    /**
     * token校验异常
     */
    @ExceptionHandler({JWTVerificationException.class})
    public Response handleJwtException(HttpServletRequest req, JWTVerificationException e) {
        log.error("token校验失败", e);
        return Response.fail(ResponseStatus.FLOW_ERROR_710, e.getMessage());
    }

    /**
     * 兜底异常处理
     */
    @ExceptionHandler(Throwable.class)
    public Response exception(HttpServletRequest req, Exception e) {
        log.error("全局异常收集器", e);
        return Response.fail(ResponseStatus.FLOW_ERROR_702, e.getMessage());
    }

}
